package fgin

import (
	"fmt"
	"strings"
	"time"

	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

var logger *zap.Logger
var logSugerBase *zap.SugaredLogger
var logSuger *FginSugaredLogger

// v2版本 兼容可以按时间分文件
func logInit() {
	defaultLogConfig := Log{
		Level:     "info",
		WriteType: 1,
	}
	if fginConfig.Log == (Log{}) {
		// 如果用户没有填写log配置,不进行初始化,使用默认配置进行初始化
		fginConfig.Log = defaultLogConfig
	}
	loggerConfig := zap.Config{}
	if fginConfig.Env == "pro" {
		loggerConfig = zap.NewProductionConfig()
	} else if fginConfig.Env == "dev" {
		loggerConfig = zap.NewDevelopmentConfig()
	} else {
		panic("日志初始化失败, 请检查配置env是否为: dev或pro")
	}
	// 统一格式化时间
	loggerConfig.EncoderConfig.EncodeTime = zapcore.TimeEncoderOfLayout("2006-01-02 15:04:05")
	logLv := zap.NewAtomicLevelAt(zap.InfoLevel)
	switch fginConfig.Log.Level {
	case "debug":
		logLv = zap.NewAtomicLevelAt(zap.DebugLevel)
	case "info":
		logLv = zap.NewAtomicLevelAt(zap.InfoLevel)
	case "warn":
		logLv = zap.NewAtomicLevelAt(zap.WarnLevel)
	case "error":
		logLv = zap.NewAtomicLevelAt(zap.ErrorLevel)
	}
	loggerConfig.Level = logLv

	switch fginConfig.Log.WriteType {
	case 2:
		logPathDir := strings.Join(DelArrItemStr(strings.Split(fginConfig.Log.LogPath, "/"), -1), "/")
		// 目录不存在则创建
		if !FileOrDirExists(logPathDir) {
			if err := MakeDirAll(logPathDir); err != nil {
				panic("日志目录不存在进行创建,创建失败:" + err.Error())
			}
		}
		// 打印到文件中
		if fginConfig.Log.LogPath == "" {
			panic("日志输入为文件,文件地址没有配置")
		}
		if fginConfig.Log.Rotate != "" {
			// 分文件
			fSugaredLoggerInit(&loggerConfig)
			return
		} else {
			// 单文件
			loggerConfig.OutputPaths = []string{fginConfig.Log.LogPath}
			loggerConfig.ErrorOutputPaths = []string{fginConfig.Log.LogPath}
		}
	}
	var err error
	logger, err = loggerConfig.Build()
	if err != nil {
		panic("创建日志对象失败:" + err.Error())
	}
	// 创建基础log对象
	logSugerBase = logger.Sugar()
	logSuger = &FginSugaredLogger{
		logSugerBase: logSugerBase,
		loggerConfig: &loggerConfig,
	}
}

// 增加日志分割
func fSugaredLoggerInit(loggerConfig *zap.Config) {
	// 更新fgin log配置
	logSuger = &FginSugaredLogger{
		logSugerBase: logSugerBase,
		loggerConfig: loggerConfig,
	}
	if !ArrayFindString([]string{"y", "M", "d", "h", "m", "s"}, fginConfig.Log.Rotate) {
		panic("日志rotate配置不正确")
	}
	checkLogPath()
}

// 检查日志文件分割path
func checkLogPath() {
	// 如果没有配置rotate，或无需记录文件，直接返回
	if fginConfig.Log.Rotate == "" || fginConfig.Log.WriteType != 2 {
		return
	}
	// 获取标识
	rotateFlag := ""
	switch fginConfig.Log.Rotate {
	case "y":
		rotateFlag = time.Now().Format("2006")
	case "M":
		rotateFlag = time.Now().Format("200601")
	case "d":
		rotateFlag = time.Now().Format("20060102")
	case "h":
		rotateFlag = time.Now().Format("2006010215")
	case "m":
		rotateFlag = time.Now().Format("200601021504")
	case "s":
		rotateFlag = time.Now().Format("20060102150405")
	default:
		panic("日志rotate配置不正确")
	}
	if logSuger.rotateFlag == rotateFlag {
		// 无需切换文件或记录文件，直接返回
		return
	}
	logSuger.rotateFlag = rotateFlag
	// 根据配置创建日志文件路径
	logPathLs := strings.Split(fginConfig.Log.LogPath, "/")
	logPathFile := strings.Split(logPathLs[len(logPathLs)-1], ".")[0]
	logPathLs = append(DelArrItemStr(logPathLs, -1), logPathFile)
	logSuger.loggerConfig.OutputPaths = []string{fmt.Sprintf("%v.%v.log", strings.Join(logPathLs, "/"), rotateFlag)}
	logSuger.loggerConfig.ErrorOutputPaths = []string{fmt.Sprintf("%v.%v.log", strings.Join(logPathLs, "/"), rotateFlag)}
	// 先关闭原来的logger
	if logger != nil {
		logger.Sync()
	}
	var err error
	logger, err := logSuger.loggerConfig.Build()
	if err != nil {
		panic("创建fgin日志对象失败:" + err.Error())
	}
	logSugerBase = logger.Sugar()
	logSuger.logSugerBase = logger.Sugar()
}

type FginSugaredLogger struct {
	logSugerBase *zap.SugaredLogger
	loggerConfig *zap.Config
	rotateFlag   string // 分割标识，年月日时分秒
}

func (s *FginSugaredLogger) Debug(args ...interface{}) {
	checkLogPath()
	s.logSugerBase.WithOptions(zap.AddCallerSkip(1)).Debug(args...)
}
func (s *FginSugaredLogger) Info(args ...interface{}) {
	checkLogPath()
	s.logSugerBase.WithOptions(zap.AddCallerSkip(1)).Info(args...)
}

func (s *FginSugaredLogger) Warn(args ...interface{}) {
	checkLogPath()
	s.logSugerBase.WithOptions(zap.AddCallerSkip(1)).Warn(args...)
}

func (s *FginSugaredLogger) Error(args ...interface{}) {
	checkLogPath()
	s.logSugerBase.WithOptions(zap.AddCallerSkip(1)).Error(args...)
}
